/*
 * Copyright 2011 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.semac.server.rpc;

import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import com.semac.client.rpc.AtividadeRPCServices;
import com.semac.server.database.classesbase.Database;
import com.semac.server.database.fetchers.AtividadeDataFetcher;
import com.semac.server.database.fetchers.InscricoesAlunoSemanacAtiva;
import com.semac.server.database.fetchers.SemanaAcademicaDataFetcher;
import com.semac.shared.exceptions.AuthenticationException;
import com.semac.shared.exceptions.RPCExceptions;
import com.semac.shared.model.Atividade;
import com.semac.shared.model.Pessoa;
import com.semac.shared.model.SemanaAcademica;

public class AtividadeRPCServicesImpl extends SemacRemoteServiceServlet implements AtividadeRPCServices {
	private static final long serialVersionUID = -5249152915687360404L;

	/**
	 * metodo monstro de insercao
	 * @throws AuthenticationException 
	 */
	@Override
	public void cadastraAtividade(Atividade atividade) throws RPCExceptions, AuthenticationException {
		if (!this.getPessoaLogadaNaSession().ehComex()){
			throw new AuthenticationException("Permissão Negada!");
		}
		
		if (atividade == null)
			return; //ou dah um throw???
		
		String virgula = "";
		String columnsToInsert = "";
		String valuesToInsert = "";
		SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");	
		
		//primeiro cadastramos os dados da atividade na tabela de atividades
		if (atividade.getCodSemac() != null){
			columnsToInsert += " \"codSemana\" ";
			valuesToInsert += atividade.getCodSemac();
			virgula = " , ";
		}		
		
		
		if (atividade.getTitulo() != null){
			columnsToInsert += virgula + " \"titulo\" ";
			valuesToInsert += virgula + "'" +  atividade.getTitulo() + "'";
			virgula = " , ";
		}
		if (atividade.getDescricao() != null){
			columnsToInsert += virgula + " \"descricao\" ";
			valuesToInsert += virgula + "'" +  atividade.getDescricao() + "'" ;
			virgula = " , ";
		}
		if (atividade.getLimiteAlunos() != null){
			columnsToInsert += virgula + " \"limiteVagas\" ";
			valuesToInsert += virgula + atividade.getLimiteAlunos();
			virgula = " , ";
		}
		
		columnsToInsert += virgula + " \"temInscricao\" ";
		valuesToInsert += virgula + atividade.isTemInscricao();
		virgula = " , ";
		
		if (atividade.getDiaDaAtividade() != null){
			columnsToInsert += virgula + " \"dataInicio\" ";					
			valuesToInsert += virgula + "'" +  dateFormatter.format(atividade.getDiaDaAtividade()) + "'";
			virgula = " , ";
		}
		
		if (atividade.getFimDaAtividade() != null){
			columnsToInsert += virgula + " \"dataFim\" ";
			valuesToInsert += virgula + "'" +  dateFormatter.format(atividade.getFimDaAtividade()) + "'" ;
			virgula = " , ";
		}
		
		
		if (atividade.getSala() != null){
			columnsToInsert += virgula + " \"sala\" ";
			valuesToInsert += virgula + "'" +  atividade.getSala() + "'";
			virgula = " , ";
		}
		
		
		Integer lastInsertedId = null;
		try {
			lastInsertedId = Database.getInstance().insert("atividade", columnsToInsert, valuesToInsert);
		} catch (SQLException e) {			
			e.printStackTrace();
			throw new RPCExceptions("Falha ao inserir atividade no banco de dados");
		}
		
		//e agora inserimos os ministrantes na tabela correspondente, se tivemos exito na insercao da atividade
		if (lastInsertedId != null)
			for (Pessoa ministrante : atividade.getMinistrantes()) {			
				try {
					Database.getInstance().insert("tutor", "\"codPessoa\",\"codAtividade\"", ministrante.getIdPessoa() + " , " + lastInsertedId)	;
				} catch (SQLException e) {
					
					e.printStackTrace();
					throw new RPCExceptions("Erro ao cadastrar ministrante como tutor da atividade \"" + atividade.getTitulo() + "\"");
				}				
			}
		
		
		
	}

	
	@Override
	public void removeAtividade(Atividade atividade) throws RPCExceptions, AuthenticationException {
		if (!this.getPessoaLogadaNaSession().ehComex()){
			throw new AuthenticationException("Permissão Negada!");
		}
		if (atividade == null)
			return;
		
		if (atividade.getId() == null)
			throw new RPCExceptions("id da atividade nula");
		
		try {
			Database.getInstance().delete("atividade", "\"codAtividade\" = " + atividade.getId());
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RPCExceptions(e.getMessage());
		}
		
	}


	/**
	 * metodo monstro de update
	 * @throws AuthenticationException 
	 */
	@Override
	public void updateAtividade(Atividade atividade) throws RPCExceptions, AuthenticationException {
		if (!this.getPessoaLogadaNaSession().ehComex()){
			throw new AuthenticationException("Permissão Negada!");
		}
		if (atividade == null)
			return; //ou dah um throw???
		
		String virgula = "";
		String set = "";
		SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");	
		
		//primeiro damos update na tabela de atividades
		if (atividade.getCodSemac() != null){
			set += virgula +  " \"codSemana\" = " + atividade.getCodSemac();
			virgula = " , ";
		}		
		if (atividade.getTitulo() != null){
			set += virgula + " \"titulo\" = '" +  atividade.getTitulo() + "'";
			virgula = " , ";
		}
		if (atividade.getDescricao() != null){
			set += virgula + " \"descricao\" = '" +  atividade.getDescricao() + "'";
			virgula = " , ";
		}
		if (atividade.getLimiteAlunos() != null){
			set += virgula + " \"limiteVagas\" = " + atividade.getLimiteAlunos();
			virgula = " , ";
		}
		set += virgula + " \"temInscricao\" = " + atividade.isTemInscricao();
		virgula = " , ";
		if (atividade.getDiaDaAtividade() != null){
			set += virgula + " \"dataInicio\" = '" +  dateFormatter.format(atividade.getDiaDaAtividade()) + "'";					
			virgula = " , ";
		}
		if (atividade.getFimDaAtividade() != null){
			set += virgula + " \"dataFim\" = '" +  dateFormatter.format(atividade.getFimDaAtividade()) + "'" ;
			virgula = " , ";
		}
		if (atividade.getSala() != null){
			set += virgula + " \"sala\" = '" +  atividade.getSala() + "'";
			virgula = " , ";
		}
		
		try {
			Database.getInstance().update("atividade", set, "\"codAtividade\" = " + atividade.getId());
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RPCExceptions("Erro ao dar update da atividade");
		}		
		
		//se tudo correu bem, deletamos as entradas de tutores na tabela de tutores referentes a essa atividade,
		try{
			Database.getInstance().delete("tutor", "\"codAtividade\" = " + atividade.getId());
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RPCExceptions("Erro ao excluir ministrantes da atividade a ser atualizada");
		}
		
		//e inserimos os ministrantes novos, atualizados
		for (Pessoa ministrante : atividade.getMinistrantes()) {			
			try {
				Database.getInstance().insert("tutor", "\"codPessoa\",\"codAtividade\"", ministrante.getIdPessoa() + " , " + atividade.getId());
			} catch (SQLException e) {				
				e.printStackTrace();
				throw new RPCExceptions("Erro ao cadastrar ministrantes ao atualizar atividade \"" + atividade.getTitulo() + "\"");
			}				
		}
		
	}
	
	
	@Override
	public ArrayList<Atividade> selecionaAtividadesLike(Atividade atividadeFiltro, boolean usandoAnd) throws RPCExceptions {

		String whereString = "";
		String operacaoComparacao;
		if (usandoAnd)
			operacaoComparacao = " AND ";
		else
			operacaoComparacao = " OR ";
		
		//se o filtro eh nulo, nao temos where... basta buscar tudo
		if (atividadeFiltro == null)
			whereString = "";
		//senao, temos que montar o filtro de where
		else{
			//adicionando filtro de id
			if (atividadeFiltro.getId() != null)
				whereString += " \"atividade\".\"codAtividade\"=" +atividadeFiltro.getId();
			//adicionando filtro de ministrante
			if (atividadeFiltro.getMinistrantes() != null && atividadeFiltro.getMinistrantes().size() > 0){
				if (!whereString.trim().equals(""))
					whereString += operacaoComparacao;
				String or = "";
				whereString += " ( ";
				for (Pessoa ministrante : atividadeFiltro.getMinistrantes()) {
					whereString += or + " \"tutor\".\"codPessoa\"=" + ministrante.getIdPessoa();
					or = " OR ";
				}
				whereString += " ) ";
			}
			//adicionando filtro de id da semac
			if (atividadeFiltro.getCodSemac() != null){
				if (!whereString.trim().equals(""))
					whereString += operacaoComparacao;
				whereString += " \"atividade\".\"codSemana\"=" +atividadeFiltro.getCodSemac();
			}
		}
		
		//pegando a implementacao do fetcher e fazendo o select no banco de dados.
		AtividadeDataFetcher atividadesFetcher= new AtividadeDataFetcher(whereString);
		
		try {
			Database.getInstance().doSelect(atividadesFetcher);
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RPCExceptions(e.getMessage());
		}
			
		
		//retorna o array de atividades pegas do banco
		return atividadesFetcher.getFetchedData();
	}


	
	
	@Override
	public void inscreveAluno(ArrayList<Atividade> atividades) throws RPCExceptions {
		try {
			
			//pega a id da semana academica ativa no momento.
			SemanaAcademicaDataFetcher semanaFetcher = new SemanaAcademicaDataFetcher("ativa = 'true'");		
			Database.getInstance().doSelect(semanaFetcher);	
			SemanaAcademica semana = semanaFetcher.getFirstOccurrence();
			Integer idSemanac = semana.getCodSemana();
			
			
			//protege inscricao com datas fora de periodo de inscricao
			if (semana.getInicioInscricao().after(new Date()) || new Date().after(semana.getFimInscricao())){
				throw new RPCExceptions("Inscrições não são permitidas para hoje!");
			}
			
			
			//daí, pega todos os ids das atividades dessa semana, para poder usar na proxima operacao do banco de dados
			AtividadeDataFetcher ativFetcher = new AtividadeDataFetcher("\"atividade\".\"codSemana\" = " + idSemanac);
			Database.getInstance().doSelect(ativFetcher);
			
			String idsAtividades = "(";
			String virgula = "";
			for (Atividade atividade : ativFetcher.getFetchedData()) {
				idsAtividades += virgula + atividade.getId();
				virgula = ",";
			}
			idsAtividades += ")";	
			
			
			//deleta todas as entradas da tabela de inscricao onde o codigo da atividade seja um dos codigos
			//de atividade que estao na semana academica ativa
			Database.getInstance().delete("\"inscricao\"", "\"codPessoa\" = " + this.getPessoaLogadaNaSession().getIdPessoa() +
												  " and \"codAtividade\" in " + idsAtividades);
			
			
			
			//depois salva as novas inscrições
			Integer pessoaID = this.getPessoaLogadaNaSession().getIdPessoa();
			String columns = "\"codPessoa\", \"codAtividade\"";
			String values = "";
			for (Atividade atividade : atividades) {
				values = pessoaID + ", " + atividade.getId();
				Database.getInstance().insert("inscricao", columns, values);
			}
			
		} catch (SQLException e1) {
			throw new RPCExceptions("Erro de banco de dados na inscrição das atividades!");
		}
		
		
	}
	
	
	


	@Override
	public ArrayList<Atividade> pegaInscricoesAluno() throws RPCExceptions {
		
		try{					
			InscricoesAlunoSemanacAtiva inscFetcher = new InscricoesAlunoSemanacAtiva(this.getPessoaLogadaNaSession());		
			//primeiro pega as ids das atividades q o aluno tá inscrito
			Database.getInstance().doSelect(inscFetcher);
			
			
			String in = "(";
			String virgula = "";
			for (Integer idsDasAtiv : inscFetcher.getFetchedData()) {
				in += virgula + idsDasAtiv;
				virgula = ",";
			}
			in += ")";
			
			//nao ha atividades em q o aluno se inscreveu
			if (in.equals("()"))
				return new ArrayList<Atividade>();
			
			//Se há atividades, pegas-as
			//pega as atividades inscritas do aluno, usando as ids pegas do banco de dados.
			AtividadeDataFetcher atividadesFetcher = new AtividadeDataFetcher("\"atividade\".\"codAtividade\" in " + in);
					
			Database.getInstance().doSelect(atividadesFetcher);
			
			return atividadesFetcher.getFetchedData();
			
		}catch (Exception e) {
			throw new  RPCExceptions("Erro ao selecionar inscrições do aluno"); 
		}
		
	}

}
